/*
 * @(#)Manager.java	1.29 02/07/31 @(#)
 *
 * Copyright (c) 2002 Sun Microsystems, Inc.  All rights reserved.
 * PROPRIETARY/CONFIDENTIAL
 * Use is subject to license terms.
 */

package javax.microedition.media;

import java.io.IOException;
import java.io.InputStream;
import java.util.Hashtable;

import android.media.MediaPlayer;



public final class Manager {

    final public static String TONE_DEVICE_LOCATOR = "device://tone";

    native private static int nPlayTone(int note, int  dur, int vol);

    private Manager() {}

    public static String [] getSupportedContentTypes(String protocol) {
	if (protocol == null)
	    return new String [] { "audio/x-wav", "audio/x-tone-seq" };
	if (protocol.equals("device"))
	    return new String [] { "audio/x-tone-seq" };
	if (protocol.equals("http"))
	    return new String [] { "audio/x-wav" };
	return new String[0];
    }

    /**
     * Return the list of supported protocols given the content
     * type.  The protocols are returned
     * as strings which identify what locators can be used for creating 
     * <code>Player</code>'s.
     * <p>
     * See <a href="#media-protocol">protocol name</a> for the syntax
     * of the protocols returned. 
     * See <a href="#content-type">content types</a> for the syntax
     * of the content type used.
     * <p>
     * For example, if the given <code>content_type</code>
     * is <code>"audio/x-wav"</code>, then the supported protocols
     * that can be used to play back <code>audio/x-wav</code>
     * will be returned.
     * <p>
     * If <code>null</code> is passed in as the 
     * <code>content_type</code>, 
     * all the supported protocols for this implementation 
     * will be returned.  The returned array must be non-empty.
     * <p>
     * If the given <code>content_type</code> is an invalid or
     * unsupported content type, then an empty array will be returned.
     *
     * @param content_type The content type for the supported protocols.
     * @return The list of supported protocols for the given content type.
     */
    public static String [] getSupportedProtocols(String content_type) {
	if (content_type == null)
	    return new String [] { "device", "http" };
	if (content_type.equals("audio/x-tone-seq"))
	    return new String [] { "device" };
	if (content_type.equals("audio/x-wav"))
	    return new String [] { "http" };
	return new String[0];
    }

    /**
     * Create a <code>Player</code> from an input locator.
     *
     * @param locator A locator string in URI syntax that describes
     * the media content.  
     * @return A new <code>Player</code>.
     * @exception IllegalArgumentException Thrown if <code>locator</code>
     * is <code>null</code>.
     * @exception MediaException Thrown if a <code>Player</code> cannot
     * be created for the given locator.
     * @exception IOException Thrown if there was a problem connecting
     * with the source pointed to by the <code>locator</code>.
     * @exception SecurityException Thrown if the caller does not
     * have security permission to create the <code>Player</code>.
     */
    public static Player createPlayer(String locator)
	throws IOException, MediaException {

	if (locator == null)
	    throw new IllegalArgumentException("locator: null");

	MediaPlayer p = null;
	boolean conn = true;
	if (locator.equals(TONE_DEVICE_LOCATOR)) {
	    p = new MediaPlayer();
	    conn = false;
	} else {
	    if (locator.toLowerCase().endsWith(".wav") ||
		locator.startsWith("http:")) {
		p = new MediaPlayer();
	    }
	}

	if (p == null)
	    throw new MediaException("Unsupported type.");
	
	
	return null;
    }

    /**
     * Create a <code>Player</code> to play back media from an 
     * <code>InputStream</code>.  
     * <p>
     * The <code>type</code> argument
     * specifies the content-type of the input media.  If 
     * <code>null</code> is given, <code>Manager</code> will
     * attempt to determine the type.  However, since determining
     * the media type is non-trivial for some media types, it
     * may not be feasible in some cases.  The
     * <code>Manager</code> may throw a <code>MediaException</code>
     * to indicate that.
     * 
     * @param stream The <code>InputStream</code> that delivers the
     * input media.
     * @param type The <code>ContentType</code> of the media.
     * @return A new <code>Player</code>.
     * @exception IllegalArgumentException Thrown if <code>stream</code>
     * is <code>null</code>.
     * @exception MediaException Thrown if a <code>Player</code> cannot
     * be created for the given stream and type.
     * @exception IOException Thrown if there was a problem reading data
     * from the <code>InputStream</code>.
     * @exception SecurityException Thrown if the caller does not
     * have security permission to create the <code>Player</code>.
     */
    public static Player createPlayer(InputStream stream, String type) 
	throws IOException, MediaException {
	if (stream == null)
	    throw new IllegalArgumentException("stream: null");

//	BasicPlayer p = null;
//
//	if (type != null) {
//	    type = type.toLowerCase();
//	}
//	if ((type == null) || 
//	    ((type != null) && (type.equals("audio/x-wav")))) {
//	    p = new WavPlayer();
//	}
//
//	if ((type != null) && (type.equals("audio/x-tone-seq"))) {
//	    p = new TonePlayer();
//	}
//
//	if (p != null) {
//	    p.setStrm(stream);
//	    p.setLocator(null, false);
//	    return p;
//	} 
	return null;
    }

    /**
     * Play back a tone as specified by a note and its duration.
     * A note is given in the range of 0 to 127 inclusive.  The frequency 
     * of the note can be calculated from the following formula:
     * <pre>
     *     SEMITONE_CONST = 17.31234049066755 = 1/(ln(2^(1/12)))
     *     note = ln(freq/8.176)*SEMITONE_CONST
     *     The musical note A = MIDI note 69 (0x45) = 440 Hz.
     * </pre>
     * This call is a non-blocking call. Notice that this method may
     * utilize CPU resources significantly on devices that don't
     * have hardware support for tone generation.
     * 
     * @param note Defines the tone of the note as specified by the 
     * above formula.
     * @param duration The duration of the tone in milli-seconds.
     * Duration must be positive.
     * @param volume Audio volume range from 0 to 100.  100 represents 
     * the maximum
     * volume at the current hardware level.  Setting the volume to a 
     * value less
     * than 0 will set the volume to 0.  Setting the volume to greater than
     * 100 will set the volume to 100. 
     *
     * @exception IllegalArgumentException Thrown if the given note or 
     * duration is out of range.
     * @exception MediaException Thrown if the tone cannot be played 
     * due to a device-related problem.
     */
    static public void playTone(int note, int duration, int volume)
	throws MediaException {
	if (note < 0 || note > 127 || duration <= 0)
	    throw new IllegalArgumentException("playTone");

	if (nPlayTone(note, duration, volume) <= 0)
	    throw new MediaException("can't play tone");
    }
}

